﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestParallel
{
    class Program
    {
        
        static void Main(string[] args)
        {
            //Test1 t1=new Test1();
            //t1.OnTimeExecTask();


            //Test2 t2 = new Test2();
            //t2.OnTimeExecTask();

            //try
            //{
            //    Test3 t3 = new Test3();
            //    t3.OnTimeExecTask();
            //}
            //catch (AggregateException e)
            //{
            //    foreach (var currentError in e.InnerExceptions)
            //    {
            //        Console.WriteLine(currentError.Message);
            //    }
            //}


            //Test4 t4=new Test4();
            //t4.OnTimeExecTask();

            //Test5 t5=new Test5();
            //t5.OnTimeExecTask();

            //Test6 t6=new Test6();
            //t6.OnTimeExecTask();

            Test7 t7=new Test7();
            t7.OnTimeExecTask();
        }
    }

    //单任务，多条处理线
    public class Test1
    {
        MsgEnity Msg = new MsgEnity();

        public void OnTimeExecTask()
        {
            Parallel.Invoke(OneTask, TwoTask, ThreeTask);
            Msg.toStr();
        }

        

        void OneTask()
        {
            Msg.OneMsg = "the first step";

        }

        void TwoTask()
        {
            Msg.TwoMsg = "the second step";

        }


        void ThreeTask()
        {
            Msg.ThreeMsg = "the third step";

        }
    }

    //耗时操作，如果存在全局变量，可能会出现（结果不是预期值）
    public class Test2
    {
        private int TotleNum = 0;
        private object Sum = 0;
        public void OnTimeExecTask()
        {
            Stopwatch sp1=new Stopwatch();
            sp1.Start();
            for (int i = 0; i < 1000; i++)
            {
                for (int j = 0; j < 1000; j++)
                {
                    TotleNum++;
                }
            }
            sp1.Stop();
            string printStr = "totle:" + TotleNum+"\r\n time:"+ sp1.ElapsedMilliseconds;
            Console.WriteLine(printStr);

            TotleNum = 0;
            Stopwatch sp2 = new Stopwatch();
            sp2.Start();
            Parallel.For(0, 1000, i =>
            {
                for (int j = 0; j < 1000; j++)
                {
                    lock (Sum)
                    {
                        Sum= (int)Sum+1;
                    }
                    
                }
            });

            printStr = "totle:" + Sum + "\r\n time:" + sp1.ElapsedMilliseconds;
            Console.WriteLine(printStr);

        }
    }

    //并行异常处理
    public class Test3
    {
        public void OnTimeExecTask()
        {
            Parallel.Invoke(Exception1,Exception2);
        }

        void Exception1()
        {
            throw new Exception("测试异常1");
        }

        void Exception2()
        {
            throw new Exception("测试异常2");
        }
    }

    //测试多线程和并行，同时执行任务
    public class Test4
    {
        public void OnTimeExecTask()
        {
            Thread[] threads=new Thread[3];
 
            for (int i = 0; i < threads.Length; i++)
            {
                threads[i]= new Thread(ExecParalle);
                threads[i].Start();
            }
        }


        void ExecParalle()
        {
            Parallel.For(0, 10, i =>
            {
                Console.WriteLine(i);
            });
        }
    }

    //测试线程安全类型(不安全)
    public class Test5
    {
        List<int>  NoSafeList=new List<int>();
        //当大于5000时，就会出现错误
        public void OnTimeExecTask()
        {
            Parallel.For(0, 5000, i =>
            {
                NoSafeList.Add(i);
            });

            Console.WriteLine(NoSafeList.Count);
        }
    }

    //测试线程安全类型(安全)
    public class Test6
    {
        ConcurrentBag<int> NoSafeList = new ConcurrentBag<int>();
        public void OnTimeExecTask()
        {
            Parallel.For(0, 10000, i =>
            {
                NoSafeList.Add(i);
            });

            Console.WriteLine(NoSafeList.Count);
        }
    }

    //parallel  使用  Linq
    public class Test7
    {
        public void OnTimeExecTask()
        {
            List<MsgEnity> list = new List<MsgEnity>();
           
            //数据超过20w条时，性能明显超过 正常linq
            for (int i = 0; i < 200000; i++)
            {
                list.Add(new MsgEnity() {Order = i,OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
                list.Add(new MsgEnity() { Order = i, OneMsg = "the:" + i });
            }
            Console.WriteLine("数据初始化完成");

            Stopwatch sw = new Stopwatch();
            sw.Start();
            var nomalList= list.Where(x => x.Order%7 == 0).ToList();
            sw.Stop();
            Console.WriteLine("nomalList cost time:" + sw.ElapsedMilliseconds);
            Console.WriteLine("nomalList count:" + nomalList.Count);

            sw.Restart();
            var parallelList = list.AsParallel().Where(x => x.Order%7 == 0).ToList();
            sw.Stop();
            Console.WriteLine("parallelList cost time:" + sw.ElapsedMilliseconds);
            Console.WriteLine("parallelList count:" + parallelList.Count);
        }

    }

    public class MsgEnity
    {
        public int Order { get; set; }

        public string OneMsg { get; set; }

        public string TwoMsg { get; set; }

        public string ThreeMsg { get; set; }

        public void toStr()
        {
            string msg = "OneMsg:" + OneMsg + "\r\n TwoMsg:" + TwoMsg + "\r\n ThreeMsg:" + ThreeMsg;
            Console.WriteLine(msg);
        }
    }

}
